home *** CD-ROM | disk | FTP | other *** search
- Listing 1
- /* ROMLDR.C EXE locator program
- written by: Charles B. Allison
- last change: 11-3-93 */
-
- #include <sys\stat.h>
- #include <io.h>
- #include <dos.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <alloc.h>
- #include <conio.h>
- #include <ctype.h>
- #include <fcntl.h>
- #include <string.h>
- #define BC 1
- /* BC is Borland c, else assume Microsoft */
- typedef struct {
- unsigned sig; /* signature = 4d5ah */
- unsigned lst_sec_lng;
- /*length of last sector in file modulo 512*/
- unsigned file_size;
- /* size of file in 512 byte pages includes hdr*/
- unsigned num_reloc;
- /* number of relocation items */
- unsigned hdr_siz;
- /* # of 16 byte paragraphs in header */
- unsigned min_ld_para;
- /* min # of paragraphs above load file */
- unsigned max_ld_para;
- /* max # of paragraphs requested by file */
- unsigned disp_stack_seg;
- /* rel displacement of stack segment */
- unsigned sp;
- /* contents of stack ptr on entry to prog */
- unsigned chksm; /* check sum for file */
- unsigned ip; /* beginning instruction ptr */
- unsigned rel_cs_seg; /* relative cs segment */
- unsigned off_reloc;
- /* offset to 1st relocation item typ. 1e */
- unsigned over_lay; /* overlay number */
- unsigned rsrved; /* ?? reserved ?? */
- /* relocation item format is seg:off location
- relative to the beginning of the code section */
- } EXE_HDR;
- struct MP_TBL {
- long addrs; /* segment beg. address */
- long haddrs; /* segment high addrs*/
- char class[12]; /* class of object */
- } maptable[120];
-
- void sort_table(void);
- void gethdr(char *bf);
- long hexcvt(char * num);
- size_t read_block(char far *segbuf,size_t segsz);
- long read_segm(int i);
- size_t write_block(char far *segbuf,size_t segsz);
- long write_segm(long segsize);
- int fix_segm(int i);
- int config(char *cfgfile);
- void term_error(int numerr);
-
- unsigned (*ch_ptr)[2];/* pointer to translation table
- [0] = offset,[1] = segment*/
- char mfile[14] = "rom.map"; /* dumy file names */
- char bfile[14] = "rom.bin";
- char efile[14] = "rom.exe";
- /*columns for starting and ending addresses in MAP */
- #define LCOL 1
- #define HCOL 8
- #ifdef BC
- #define MAPCOL 41;
- /*bc map file class column*/
- #else
- #define MAPCOL 45;
- /*ms map file class column */
- #endif
- int class_loc = MAPCOL;
- FILE *mapfile,*exefile,*binfile;
- #define BUF_SIZE 60
- char mapstring[BUF_SIZE];
- long fsize; /*number of bytes in exe file */
- int nsegs; /* number of segments in map */
- unsigned romsadr = 0xf000,ramsadr=0x40;
- char header[10000];
- EXE_HDR *filhdr = (EXE_HDR *)header;
- char far *seg_buffer;
- int next_fix = 0;
- char ram_class[15] = "FAR_DATA";
- unsigned ramdata; /* beginning ram segment*/
- /* ************ main ************* */
- int main(int argc,char *argv[])
- {
- int r_class_flag=1,i;
- long tmp,ssize;
-
- if((seg_buffer = (char far *) farmalloc(0x10000L))
- == NULL) term_error(0);
- if(argc == 1) term_error(-1); /*any cfg file name? */
- config(argv[1]);
- i=0;
- while (fgets(mapstring,BUF_SIZE,mapfile))
- {
- /* process map file from mapstring input */
- /* maptable[1] - n contains the segments -
- class STACK should be last one */
- /* ends with i having n+1 segments */
- if( (int)strlen(mapstring) > class_loc+1)
- { /* get rid of \n at end of string */
- mapstring[(int)strlen(mapstring)-1]='\0';
- if((tmp = hexcvt(&mapstring[LCOL])) >= 0)
- {
- maptable[i].addrs = tmp;
- maptable[i].haddrs=hexcvt(&mapstring[HCOL]);
- &mapstring[class_loc]);
- strcpy(maptable[i].class,
- &mapstring[class_loc]);
- if(r_class_flag)
- if(strcmp(&mapstring[class_loc],ram_class)==0)
- { /*set it to first class occurance*/
- ramdata = (maptable[i].addrs) >>4;
- r_class_flag = 0;
- }
- printf("\n Segment %4.4lx Class %s",
- maptable[i].addrs/16,maptable[i].class);
- i++;
- }/* end - if hexcvt */
- } /* end if strlen */
- if(i>=119) break; /* error too many segments */
- } /* end while */
- if(feof(mapfile))
- printf("\nend of file\n");
- else
- printf("\nerror reading map file\n");
- nsegs = i-1; /* number of segments [1 to nsegs] */
- gethdr(header); /* read in the exe header info */
- /* size of object section of file */
- fsize = (long) ((512L * (filhdr->file_size-1)) +
- filhdr->lst_sec_lng - 16L * filhdr->hdr_siz);
- printf("\nStartup Address %4.4x:%4.4x\n",romsadr+
- filhdr->rel_cs_seg,filhdr->ip);
- printf("Rom Size %lx\n",fsize);
- /* process the exe file header - sort fix ups */
- sort_table();
- /* read in exe file by segment
- do fixups from map table and
- write it to output file */
- for(i=0;i < nsegs;i++)
- {
- if((ssize = read_segm(i)) > 0L )
- { /* ignore 0 length segments */
- fix_segm(i);
- write_segm(ssize );
- }
- }
- /* done - end the program */
- farfree(seg_buffer);
- fcloseall();
- return 0;
- }
- /* ****************** */
- /* qsort routine for far pointers */
- int cmp_ptr(const void *a, const void *b)
- {
- long vala,valb;
- vala=((long)((unsigned *)a)[0])+
- (((unsigned *)a)[1]<<4);
- valb=((long)((unsigned *)b)[0])+
- (((unsigned *)b)[1]<<4);
- vala -= valb;
- if(vala < 0) return -1;
- if(vala > 0) return 1;
- return 0;
- }
- /* ------ sort_table -------- */
- /* sort header table */
- void sort_table(void)
- {
- qsort((void *)&header[filhdr->off_reloc],
- filhdr->num_reloc,4,cmp_ptr);
- }
- /* ------- read_block -------- */
- size_t read_block(char far *segbuf,size_t segsz)
- {
- if(fread(segbuf,1,segsz,exefile) != segsz)
- term_error(-7);
- return segsz;
- }
- /* ------- read_segm --------- */
- long read_segm(int i)
- {
- long segsize;
- segsize = maptable[i].haddrs - maptable[i].addrs;
- if(!segsize) return 0;
- segsize += maptable[i+1].addrs-(maptable[i].haddrs);
- if(segsize <= 0x8000)
- { read_block(seg_buffer,(size_t)segsize);
- } else {
- read_block(seg_buffer,0x8000);
- read_block((&seg_buffer[0x8000]),
- (size_t)(segsize-0x8000));
- }
- return segsize;
- }
- /* --------- write_block ---------- */
- size_t write_block(char far *segbuf,size_t segsz)
- {
- if(fwrite(segbuf,1,segsz,binfile) != segsz)
- term_error(-8);
- return segsz;
- }
- /* -------- write_segm --------- */
- long write_segm(long segsize)
- {
- if(!segsize) return 0;
- if(segsize <= 0x8000)
- { write_block(seg_buffer,segsize);
- } else {
- write_block(seg_buffer,0x8000);
- write_block((&seg_buffer[0x8000]),
- (size_t)(segsize-0x8000));
- }
- return segsize;
- }
- /* ------ fix_segm ------- */
- int fix_segm(int i)
- {
- unsigned tmp,cseg,fixup;
- unsigned far * fixptr;
- cseg = (unsigned)(maptable[i].addrs/16L);
- while(next_fix < filhdr->num_reloc)
- {
- if(ch_ptr[next_fix][1] > cseg) break;
- tmp = ch_ptr[next_fix][0]; /*offset into buffer*/
- fixptr = (unsigned far *) &seg_buffer[tmp];
- fixup = *fixptr;
- /* modify segment fixup according to type */
- if(fixup >= ramdata)
- {/* modify for ram */
- fixup -= ramdata;
- fixup += ramsadr;
- }
- else
- {/* handle as rom */
- fixup += romsadr;
- }
- *fixptr = fixup;
- next_fix++;
- } /*end while */
- return 0 ;
- }
- /* -------- hexcvt ------- */
- /* do hex digits to unsigned long */
- long hexcvt(char * num)
- {
- char *term;
- long value;
- value = strtoul(num,&term,16);
- return value;
- }
- /* ------- gethdr -------- */
- void gethdr(char *buf )
- {
- int i,j=32; /*index counter */
- if(fread(&buf[0],1,32,exefile) < 32)
- term_error(-6);
- /* have filhdr contents so get size of full header */
- if(fread(&buf[j],16,filhdr->hdr_siz-2,exefile)
- < filhdr->hdr_siz-2) term_error(-6);
- (unsigned *)ch_ptr =
- (unsigned *)(&buf[filhdr->off_reloc]);
- /* get address of relocation table - ch_ptr [n][m]
- m - 0 offset, 1 - seg, n relocation # */
- }
- /*----------- config -------------*/
- /* get configuration data */
- int config(char *cfgfile)
- {
- FILE *cfg;
- char buf[80];
- if((cfg = fopen(cfgfile,"r"))==NULL) term_error(-1);
- if(fgets(buf,80,cfg) == NULL) term_error(-2);
- if(sscanf(buf,"%s %s %s",&mfile,
- &efile, &bfile) != 3) term_error(-2);
- /* Now try to open input file 1 */
- if((mapfile=fopen(mfile,"r"))==NULL) term_error(-3);
- if((exefile=fopen(efile,"rb"))==NULL) term_error(-4);
- if((binfile=fopen(bfile,"wb"))==NULL) term_error(-5);
- if(fgets(buf,80,cfg) == NULL) term_error(-7);
- if(sscanf(buf,"%4x %4x",&romsadr,
- &ramsadr) != 2) term_error(-7);
- if(fgets(buf,80,cfg) == NULL) term_error(-7);
- if(sscanf(buf,"%s",&ram_class) != 1) term_error(-7);
- return 0;
- }
- /* error handler */
- char *errlist[10] = {
- "Memory Allocation Error",
- "No configuration file, USAGE:romldr cfgfile.cfg",
- "Configuration file error - File names", //-2
- "Map File open error", //-3
- "Exe File open error", //-4
- "Bin File open error", //-5
- "Error reading header", //-6
- "Error reading exe file", //-7
- "Error writing bin file", //-8
- " "
- };
- void term_error(int errnum)
- {
- errnum = abs(errnum);
- if(errnum >= 9) exit(-1);
- printf("%s\n",errlist[errnum]);
- farfree(seg_buffer);
- exit(errnum);
- }
-
-